//
//  DFLineChartView.swift
//  MoyoungHome
//
//  Created by 李然 on 2022/9/23.
//

import Foundation
import Charts
import SwiftDate
import RxSwift
import RxCocoa
import UIKit

public struct DFLineChartViewConfig {
    
    /// x轴文字字体
    public var xAxisLabelFont: UIFont
    
    /// x轴文字颜色
    public var xAxisLabelTextColor: UIColor
    
    /// x轴颜色
    public var xAxisLineColor: UIColor
    
    /// X轴厚度
    public var xAxisLineHeight: CGFloat
    
    /// y轴动画
    public var yAxisDuration: TimeInterval
    
    /// 是否显示虚线
    public var leftAxisLimit : Bool
    
    /// 虚线距离底部距离
    public var limit : CGFloat
    
    /// 虚线颜色
    public var lineColor: UIColor


    public init(xAxisLabelFont: UIFont = .systemFont(ofSize: 10), xAxisLabelTextColor: UIColor = .black, xAxisLineColor: UIColor = .gray, xAxisLineHeight: CGFloat = 1, yAxisDuration: TimeInterval = 0, leftAxisLimit: Bool = false, limit: CGFloat = 0, lineColor: UIColor = UIColor.init(hex: "#FF3333")!) {
        
        self.xAxisLabelFont = xAxisLabelFont
        self.xAxisLabelTextColor = xAxisLabelTextColor
        self.xAxisLineColor = xAxisLineColor
        self.xAxisLineHeight = xAxisLineHeight
        self.yAxisDuration = yAxisDuration
        self.leftAxisLimit = leftAxisLimit
        self.limit = limit
        self.lineColor = lineColor
        
    }
}


public class DFLineChartView:LineChartView{
    
    public private(set) var selectIndex = BehaviorRelay<Int>(value: 0)
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        
        setDefaultChart()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setDefaultChart(){
        
        self.minOffset = 16
        
        self.noDataText = "page_no_data".language
        self.isUserInteractionEnabled = false
        
        self.pinchZoomEnabled = false
        self.setScaleEnabled(false)
        self.drawGridBackgroundEnabled = false
        self.legend.enabled = false
        self.leftAxis.enabled = false
        self.rightAxis.enabled = false
        self.highlightPerTapEnabled = false
        self.highlightPerDragEnabled = false

        configDefauldXAxis()
    }
    
    private func configDefauldXAxis(){
        self.xAxis.drawGridLinesEnabled = false
        self.xAxis.labelPosition = .bottom
        self.xAxis.granularity = 1
    }
    
    
    /// 设置触摸位置，目前只用x轴位置
    public func setTouchLocation(_ location:CGPoint){
        let higtlight = self.getHighlightByTouchPoint(CGPoint(x: location.x, y: 1))
        if let higtlight = higtlight,self.highlighted.contains(higtlight) {
            return
        }
        self.highlightValue(higtlight)
        if let x = higtlight?.x{
            self.selectIndex.accept(Int(x))
        }
        
    }
    
    /// 设置markerView，柱状图上面的气泡
    public func setMarkerView(_ view:MarkerView){
        view.chartView = self
        self.marker = view
    }
    
    /// 在固定Bar 上显示marker
    public func showMarkerViewOfBar(index:Int) {
        setHighLightValue(x: index)
    }
    
    /// 设置barChart bar 高亮
    public func setHighLightValue(x:Int) {
        self.highlightValue(x: Double(x), dataSetIndex: 0)
    }
    
    /// 设置Y轴最大值，应是数据的最大值，数组其他数据设置一个默认最小值，为最大值的10%
    public func setYMax(value:Double){
        self.leftAxis.axisMaximum = value
        self.rightAxis.axisMaximum = value
    }
    
    /// 设置Y轴最小值
    public func setYMin(value:Double){
        self.leftAxis.axisMinimum = value
        self.rightAxis.axisMinimum = value
        
       
    }
    
    /// 设置UI配置
    public func setConfig(_ config:DFLineChartViewConfig){
        
        self.animate(yAxisDuration: config.yAxisDuration)

        self.xAxis.axisLineWidth = config.xAxisLineHeight
        self.xAxis.labelFont = config.xAxisLabelFont
        self.xAxis.labelTextColor = config.xAxisLabelTextColor
        self.xAxis.axisLineColor = config.xAxisLineColor
        
        self.leftAxis.enabled = config.leftAxisLimit
        self.leftAxis.drawGridLinesEnabled = false
        self.leftAxis.drawLabelsEnabled = false
        self.leftAxis.axisLineWidth = 0
        
        self.leftAxis.removeAllLimitLines()
        
        let line = ChartLimitLine()
        line.lineColor = config.lineColor
        line.lineDashLengths = [1,1]
        line.limit = config.limit
        self.leftAxis.addLimitLine(line)
    }
    
    /// x轴标签格式化器
    public func setXAxis(valueFormatter:IAxisValueFormatter){
        self.xAxis.valueFormatter = valueFormatter
    }
    
    /// 柱子数量
    public func setBarCount(_ count:Int){
        self.xAxis.labelCount = count
    }

    
    /// 设置柱状图数据
    /// - Parameters:
    ///   - barDataList: 数据源
    ///   - drawValue: 是否显示数字
    ///   - barWidth: 状图和空白条比例
    ///   - barColor: 默认颜色
    ///   - barHighLichtColor: 高亮颜色值
    public func setData(_ lineDataList:[Double] ,
                        lineColor:UIColor,
                        gradientColors:[UIColor],
                        lineWidth:Double, circleRadius: CGFloat? = nil){
        
        clear()
        

        guard lineDataList.count > 0 else {
            return
        }
        let yVals = lineDataList.enumerated().map { (index,element) -> BarChartDataEntry in
            return BarChartDataEntry(x: Double(index), y: element)
        }
        
        let dataSet:LineChartDataSet = LineChartDataSet(entries: yVals, label: "")
        dataSet.mode = LineChartDataSet.Mode.cubicBezier
        dataSet.cubicIntensity = 0.2
        dataSet.drawFilledEnabled = true
        
        let drawCircle = lineDataList.count <= 1
        dataSet.drawCirclesEnabled = drawCircle
        dataSet.setCircleColor(lineColor)
        dataSet.drawCircleHoleEnabled = true
        dataSet.circleRadius = circleRadius ?? lineWidth / 2
        dataSet.lineWidth = lineWidth
        
        dataSet.setColor(lineColor)
        
        let gradient = CGGradient(colorsSpace: nil, colors: gradientColors.map{$0.cgColor} as CFArray, locations: nil)!
        dataSet.fillAlpha = 1
        dataSet.fill = LinearGradientFill(gradient: gradient, angle: 90)
        
        dataSet.setDrawHighlightIndicators(false)
        
        let data = LineChartData(dataSet: dataSet)
        data.setDrawValues(false)
        self.data = data

    }
}


public class LinearGradientFill: Fill
{

    public let _gradient: CGGradient
    public let angle: CGFloat

    init(gradient: CGGradient, angle: CGFloat = 0)
    {
        self._gradient = gradient
        self.angle = angle
        super.init()
    }

    public override func fillPath(context: CGContext, rect: CGRect)
    {
        context.saveGState()
        defer { context.restoreGState() }

        let radians = (360.0 - angle).DEG2RAD
        let centerPoint = CGPoint(x: rect.midX, y: rect.midY)
        let xAngleDelta = cos(radians) * rect.width / 2.0
        let yAngleDelta = sin(radians) * rect.height / 2.0
        let startPoint = CGPoint(
            x: centerPoint.x - xAngleDelta,
            y: centerPoint.y - yAngleDelta
        )
        let endPoint = CGPoint(
            x: centerPoint.x + xAngleDelta,
            y: centerPoint.y + yAngleDelta
        )

        context.clip()
        context.drawLinearGradient(
            _gradient,
            start: startPoint,
            end: endPoint,
            options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]
        )
    }
}

extension FloatingPoint
{
    var DEG2RAD: Self
    {
        return self * .pi / 180
    }

    var RAD2DEG: Self
    {
        return self * 180 / .pi
    }

    /// - Note: Value must be in degrees
    /// - Returns: An angle between 0.0 < 360.0 (not less than zero, less than 360)
    var normalizedAngle: Self
    {
        let angle = truncatingRemainder(dividingBy: 360)
        return (sign == .minus) ? angle + 360 : angle
    }
}
